<!DOCTYPE html>
<html lang="zh-cn">

<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	
	<title>划水王  | js 拾遗</title>
	<meta name="viewport" content="width=device-width,minimum-scale=1">
	<meta name="generator" content="Hugo 0.74.1" />
	
	
	<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
	

	
	
	<link href="/dist/app.css" rel="stylesheet">
	

	

	
	
	

	
	
	
	
	
	<script>
		(function (u, c) {
			var d = document,
				t = 'script',
				o = d.createElement(t),
				s = d.getElementsByTagName(t)[0];
			o.src = u;
			if (c) {
				o.addEventListener('load', function (e) {
					c(e);
				});
			}
			s.parentNode.insertBefore(o, s);
		})('https:\/\/flwwsg.gitee.io\/lib\/pangu.min.js', function () {
			pangu.spacingPage();
		});
	</script>
	
	
	
</head>

<body class="bg-gray-100 text-gray-700 font-sans">
	<div class="p-6 sm:p-10 md:p-16 flex flex-wrap">
		<header class="w-full md:w-2/5 xl:w-1/2 md:pr-12 lg:pr-20 xl:pr-24 order-1 md:order-1 max-w-2xl">
			<div
				class="z-50 bg-gray-100 bg-opacity-75 bg-opacity-custom lg:min-w-0.7 max-w-xl md:float-right md:text-right leading-loose tracking-tight md:sticky md:top-0 pt-2">
				
<div>
	<h2>
		<a href="https://flwwsg.gitee.io" title="划水王" class="heading font-cursive icon">划水王</a>
	</h2>
</div>
<h1 class="pt-2">js 拾遗</h1>

<div class="flex flex-wrap justify-end pt-2 "><div class="md:flex-grow-0 font-light">
	

	

	
</div><time class="text-eucalyptus-500 md:text-right md:flex-grow font-light pl-4"
		datetime="2020-07-22T23:34:57&#43;08:00">2020-7-22 23:34</time>
</div>

<hr />

			</div>
		</header>
		<main role="main" class="w-full md:w-3/5 xl:w-1/2 max-w-3xl order-2 md:order-2 min-h-70vh pt-2 pb-4">
			

<article>
	<section class="mx-auto content">
		<div class="c-rich-text"><!-- raw HTML omitted -->
<h3 id="var-x--y--100">var x = y = 100</h3>
<p>右边的表达式 y = 100，隐式声明了一个全局变量y，且赋值100。(非 strict mode)
TODO add 浏览器变量</p>
<h3 id="ax--a--n2">a.x = a = {n:2}</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">n</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span>};
<span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">n</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span>};
</code></pre></div><p><strong>js总是从左到右赋值</strong>，所以a.x总是最先被计算求值。</p>
<ul>
<li>a.x的计算结果引用了原始变量a，通过这个引用保存了a变量({n: 1})</li>
<li>上面发生了2次赋值，第一次赋值发生于&quot;a = {n: 2}&rdquo; , 覆盖了原始变量a.</li>
<li>第二次赋值发生于被&quot;a.x&quot;引用暂存的原始变量a。</li>
<li>原始变量a({n: 1})被抛弃，a被重新赋值为{n: 2}，所以最终a.x 为undefined。</li>
</ul>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">&gt; a
<span style="color:#f92672">{</span> n: <span style="color:#ae81ff">2</span> <span style="color:#f92672">}</span>
&gt; a.x
undefined
</code></pre></div><p>此操作意味着给<strong>旧的变量添加一个指向新变量的属性</strong>。如</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">n</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span>} , <span style="color:#a6e22e">ref</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">a</span>;
<span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">n</span><span style="color:#f92672">:</span><span style="color:#ae81ff">2</span>}

</code></pre></div><p>结果</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">&gt; a
<span style="color:#f92672">{</span> n: <span style="color:#ae81ff">2</span> <span style="color:#f92672">}</span>
&gt; ref
<span style="color:#f92672">{</span> n: 1, x: <span style="color:#f92672">{</span> n: <span style="color:#ae81ff">2</span> <span style="color:#f92672">}</span> <span style="color:#f92672">}</span>
</code></pre></div><!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<h3 id="break-标签">break 标签</h3>
<p>跳转到标签处</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<h3 id="类与构造器">类与构造器</h3>
<p>js 一方面使用了类继承的基础结构和概念，另一方面又要实现原型继承和基于原型链检查的逻辑</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">Device</span>() {
    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">id</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
}

<span style="color:#66d9ef">function</span> <span style="color:#a6e22e">Car</span>() {
    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">name</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Car&#34;</span>;
    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">color</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Red&#34;</span>;
}
<span style="color:#a6e22e">Car</span>.<span style="color:#a6e22e">prototype</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Device</span>();

<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Car</span>();
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">x</span>.<span style="color:#a6e22e">id</span>);
</code></pre></div><p><strong>super</strong>，出现的目的解决在“类抄写”导致子类覆盖时，父类能力丢失问题。为每个方法添加一个“所属的类”的性质，称之为“主对象(HomeObject)”
TODO add 浏览器 this</p>
<h3 id="严格模式">严格模式</h3>
<p>所谓严格模式，从来都不是一种环境模式。所有的执行环境&ndash;执行上下文，以及它们所引用的环境(Environment)都没有严格模式这样的模式，也没有这样的性质。
严格模式不过是代码执行过程中的一个限制。</p>
<h3 id="变量提升hoisting">变量提升(hoisting)</h3>
<p>在 javaScript 代码执行过程中，javaScript 引擎把变量的声明部分和函数的声明部分提升到代码开关的行为。变量提升后，会给变量设置默认值
即 undefined。js经过编译后，会生成2部分内容：执行上下文(Execution context)和可执行代码。</p>
<h4 id="执行上下文">执行上下文</h4>
<p>执行上下文是js执行一段代码时的运行环境。该对象保存了变量提升的内容，包括变量环境，词法环境，外部环境，this。三种情况下，引擎会在执行前编译并创建执行上下文。</p>
<ul>
<li>js执行全局代码时，会编译全局代码并创建全局执行上下文。全局执行上下文在整个页面的生存周期内，只有一份。(全局执行上下文)</li>
<li>调用一个函数时，函数体内的代码会被编译，并创建函数执行上下文。正常情况下，函数执行结束之后，创建函数执行上下文会被销毁。(函数执行上下文)</li>
<li>使用 eval 函数时，eval 中的代码也会被编译，并创建执行上下文。(eval 执行上下文)</li>
</ul>
<h3 id="作用域scope">作用域(scope)</h3>
<p>es6前只包含全局作用域和函数作用域，es6 通过配合 let、const引入块级作用域。
块级作用域通过词法环境的栈结构来实现，变量提升通过变量环境来实现，由此js引擎同时变量提升和块级作用域。</p>
<h4 id="暂时性死区">暂时性死区</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">index</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
{
    <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">index</span>);
    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">index</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;
}
</code></pre></div><p>输出结果： Cannot access &lsquo;index&rsquo; before initialization。
在块作用域内，let 声明的变量被提升，但只是创建被提升，初始化并未提升，在初始化之前使用此变量，就会形成暂时性死区。</p>
<h4 id="作用域链">作用域链</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">foo</span>() {
    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">myName</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;foo name&#34;</span>;
    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">test1</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">test2</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;
    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">innerBar</span> <span style="color:#f92672">=</span> {
        <span style="color:#a6e22e">getName</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span> () {
            <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">test1</span>);
            <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">myName</span>;
        },
        <span style="color:#a6e22e">setName</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">newName</span>) {
            <span style="color:#a6e22e">myName</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">newName</span>;
        }       
    }
    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">innerBar</span>;
}

<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">bar</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">foo</span>();
<span style="color:#a6e22e">bar</span>.<span style="color:#a6e22e">setName</span>(<span style="color:#e6db74">&#34;bar name&#34;</span>);
<span style="color:#a6e22e">bar</span>.<span style="color:#a6e22e">getName</span>();
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">bar</span>.<span style="color:#a6e22e">getName</span>());
</code></pre></div><p>根据词法作用域的规则，内部函数 getName 和 setName 总是可以访问它们的外部函数 foo 中的变量，所以当 innerBar 对象返回给全局变量 bar时，
虽然 foo 函数已经执行结束，但是 getName 和 setName 依然可以使用 foo 函数中的变量 myName 和 test1。像 setName 和 getName 方法背的
一个专属背包，无论哪里调用了 setName 和 getName 方法，它们都会背着这个 foo 函数的专属背包。之所以称之为专属背包，是因为除了 setName 和
getName 函数之外，其他任何地方都是无法访问该背包的。可以称为 foo 函数的闭包。</p>
<p><strong>闭包</strong>，根据词法作用域的规则，内部函数总是可以访问外部函数声明的变量，当通过调用一个外部函数返回一个内部函数后，即使该外部函数已经执行结束，
但内部函数引用的变量依然保存在内存中，我们把这些变量的集合称为闭包。</p>
<h4 id="this">this</h4>
<h5 id="全局上下文中的-this">全局上下文中的 this</h5>
<p>全局上下文中的this，指的是 windows 对象。</p>
<h5 id="函数执行上下文中的-this">函数执行上下文中的 this</h5>
<p>在全局环境中调用一个函数，函数内部的 this 指向的是全局变量 window</p>
<p>可以通过3种方式设置函数执行上下文中的 this 值。</p>
<ul>
<li>通过函数的 call， bind， apply 方法设置</li>
</ul>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js">
<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">bar</span> <span style="color:#f92672">=</span> {
    <span style="color:#a6e22e">myName</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;bar&#34;</span>,
    <span style="color:#a6e22e">test1</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span>
}

<span style="color:#66d9ef">function</span> <span style="color:#a6e22e">foo</span>() {
    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">myName</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;foo&#34;</span>;
}
<span style="color:#75715e">// 输出 bar
</span><span style="color:#75715e"></span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">bar</span>.<span style="color:#a6e22e">myName</span>);
<span style="color:#a6e22e">foo</span>.<span style="color:#a6e22e">call</span>(<span style="color:#a6e22e">bar</span>);
<span style="color:#75715e">// 输出foo
</span><span style="color:#75715e"></span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">bar</span>.<span style="color:#a6e22e">myName</span>);
<span style="color:#75715e">// 提示会定义
</span><span style="color:#75715e"></span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">myName</span>);

</code></pre></div><ul>
<li>通过对象调用方法设置。</li>
<li>
<ul>
<li>使用对象来调用其内部的一个方法，该方法的 this 是指向对象本身的。</li>
</ul>
</li>
<li>
<ul>
<li>在全局环境中调用一个函数，函数内部的 this 指向的是全局变量 window。</li>
</ul>
</li>
</ul>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">myObj</span> <span style="color:#f92672">=</span> {
    <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;myObj&#34;</span>,
    <span style="color:#a6e22e">showThis</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span> () {
        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">this</span>)
    }
}

<span style="color:#a6e22e">myObj</span>.<span style="color:#a6e22e">showThis</span>();
<span style="color:#75715e">// 在全局环境中调用一个函数，函数内部的 this 指向的是全局变量 window。
</span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">foo</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">myObj</span>.<span style="color:#a6e22e">showThis</span>;
<span style="color:#a6e22e">foo</span>();
</code></pre></div><ul>
<li>通过构造函数设置</li>
</ul>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">CreateObj</span>() {
    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">name</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;myObj&#34;</span>;
}
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">myObj</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">CreateObj</span>();
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">myObj</span>.<span style="color:#a6e22e">name</span>);
</code></pre></div><h4 id="缺陷">缺陷</h4>
<ul>
<li>普通函数中的 this 默认指向全局对象 windows</li>
<li>嵌套函数中的 this 不会从外层函数中继承</li>
</ul>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js">
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">myObj</span> <span style="color:#f92672">=</span> {
    <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;myObj&#34;</span>,
    <span style="color:#a6e22e">showThis</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span> () {
        <span style="color:#75715e">// myObj 对象
</span><span style="color:#75715e"></span>        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">this</span>);
        <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">bar</span>() {
            <span style="color:#75715e">// 打印的 windows 对象
</span><span style="color:#75715e"></span>            <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">this</span>);
        }
        <span style="color:#a6e22e">bar</span>();
    }
}
<span style="color:#a6e22e">myObj</span>.<span style="color:#a6e22e">showThis</span>();

</code></pre></div><p>可以通过声明一个 self 变量来保存 this</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">myObj</span> <span style="color:#f92672">=</span> {
    <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;myObj&#34;</span>,
    <span style="color:#a6e22e">showThis</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span> () {
        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">this</span>);
        <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">self</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">this</span>;
        <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">bar</span>() {
            <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">self</span>);
        }
        <span style="color:#a6e22e">bar</span>();
    }
}
<span style="color:#a6e22e">myObj</span>.<span style="color:#a6e22e">showThis</span>();
</code></pre></div><p>也可以使用 es6 中的箭头函数来解决</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">myObj</span> <span style="color:#f92672">=</span> {
    <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;myObj&#34;</span>,
    <span style="color:#a6e22e">showThis</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span> () {
        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">this</span>);
        <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">self</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">this</span>;
        <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">bar</span> <span style="color:#f92672">=</span> () =&gt; {
            <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">this</span>);
        }
        <span style="color:#a6e22e">bar</span>();
    }
}
<span style="color:#a6e22e">myObj</span>.<span style="color:#a6e22e">showThis</span>();
</code></pre></div></div>
	</section>


</article>

		</main>
		<aside role="contentinfo"
			class="w-full md:w-2/5 xl:w-1/2 md:pr-12 lg:pr-20 xl:pr-24 order-4 md:order-3 md:sticky md:bottom-0 self-end max-w-2xl">
			<div class="md:float-right md:text-right leading-loose tracking-tight md:mb-2">
				
	<div class="md:max-w-xs  flex flex-col md:items-end">
	<ul class="font-serif flex-grow-0 flex justify-between flex-wrap md:flex-col">
	
	
</ul>
	

<div class="flex flex-wrap-reverse md:justify-end content-end md:content-start justify-start items-start   max-h-16">
	
</div>
	<div class="text-sm text-gray-500 leading-tight a-gray">
		
		<br />
		Built with Hugo and theme <a href="https://github.com/heyeshuang/hugo-theme-tokiwa">Tokiwa</a>. 446 words in this page.
	</div>
</div>

			</div>
		</aside>
		<footer class="w-full md:w-3/5 xl:w-1/2 order-3 max-w-3xl md:order-4 pt-2">
			
<hr class="double-line" />
<div class="flex flex-wrap justify-between pb-2 leading-loose font-serif">
    
    
</div>
<div >



</div>
<hr />
<div class="pb-2">
    
</div>
<hr />

		</footer>
		

<script src="/dist/app.js"></script>


	</div>
</body>

</html>